#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

//linux3.13.6 include/media/rc-core.h
//#define MS_TO_NS(msec)          ((msec) * 1000 * 1000)
#define MS_TO_NS(x) (x * 1E6L)

static struct hrtimer slam_hrtimer;
ktime_t ktime;
unsigned long mdelay = 200L;

enum hrtimer_restart slam_hrtimer_callback(struct hrtimer * timer)
{
	printk("<1>slam_hrtimer_callback called(%ld).\n", jiffies);

	hrtimer_forward(&slam_hrtimer, timer->base->get_time(), ktime);
	return HRTIMER_RESTART;
	/* Or:
	hrtimer_start(&slam_hrtimer, ktime, HRTIMER_MODE_REL);
	return HRTIMER_NORESTART;
	*/
}

int init_module(void)
{
	printk("<1>HR timer init.\n");

	ktime = ktime_set(0, MS_TO_NS(mdelay));
	hrtimer_init(&slam_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	slam_hrtimer.function = &slam_hrtimer_callback;

	printk("<1>Start hrtimer to fire in %ld ms(%ld).\n", mdelay, jiffies);
	hrtimer_start(&slam_hrtimer, ktime, HRTIMER_MODE_REL);

	return 0;
}

void cleanup_module(void)
{
	int ret = hrtimer_cancel(&slam_hrtimer);
	if (ret) printk("<1>The hrtimer is still in use!\n");

	printk("<1>HR timer exit.\n");
}

MODULE_LICENSE("GPL");
